import React, { PureComponent, Fragment } from 'react';
import { Card, Form, Row, Col, Input, Table, Select, Button, Popover, Alert, message, Badge } from 'antd';
import { connect } from 'dva';
import lodash from 'lodash';
import Bind from 'lodash-decorators/bind';
import Debounce from 'lodash-decorators/debounce';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import Ellipsis from '../../components/Ellipsis';
import { SorterOrderMapper, ResourcesTypeArray, NeedAuthorizationArray, ResourcesTypeMapper, TargetExistMapper, NeedAuthorizationMapper } from '../../utils/enum';
// import classNames from 'classnames';
import styles from './Authorization.less';

@connect(({ AuthorizationModel, GlobalEnumModel, loading }) => ({
  AuthorizationModel,
  GlobalEnumModel,
  findUserByPageLoading: loading.effects['AuthorizationModel/findUserByPage'],
  findRoleByPageLoading: loading.effects['AuthorizationModel/findRoleByPage'],
  findPermissionByPageLoading: loading.effects['AuthorizationModel/findPermissionByPage'],
  findRoleNameByUserLoading: loading.effects['AuthorizationModel/findRoleNameByUser'],
  findPermissionStrByRoleLoading: loading.effects['AuthorizationModel/findPermissionStrByRole'],
  singleUserBindRoleLoading: loading.effects['AuthorizationModel/singleUserBindRole'],
  singleUserUnBindRoleLoading: loading.effects['AuthorizationModel/singleUserUnBindRole'],
  singleRoleBindPermissionLoading: loading.effects['AuthorizationModel/singleRoleBindPermission'],
  singleRoleUnBindPermissionLoading: loading.effects['AuthorizationModel/singleRoleUnBindPermission'],
}))
@Form.create()
export default class Authorization extends PureComponent {

  state = {
    screenHeight: document.documentElement.clientHeight,
  };

  // 数据初始化
  componentDidMount() {
    window.addEventListener('resize', this.handleHeight);
    const { dispatch } = this.props;
    dispatch({ type: 'GlobalEnumModel/allSysName' });
    dispatch({ type: 'AuthorizationModel/findUserByPage' });
    dispatch({ type: 'AuthorizationModel/findRoleByPage' });
    dispatch({ type: 'AuthorizationModel/findPermissionByPage' });
  }

  // 组件卸载
  componentWillUnmount() {
    window.removeEventListener('resize', this.handleHeight);
  }

  // 动态设置高度
  @Bind()
  @Debounce(600)
  handleHeight = () => {
    const screenHeight = document.documentElement.clientHeight;
    this.setState({ screenHeight });
  }

  getHeight = () => {
    const { screenHeight } = this.state;
    let height = screenHeight - 255;
    if (height <= 300) height = 600;
    return height;
  }

  // 查询数据
  findUserByPage = (queryParam) => {
    const { dispatch } = this.props;
    dispatch({ type: 'AuthorizationModel/findUserByPage', payload: { ...queryParam, pageNo: 0 } });
    dispatch({ type: 'AuthorizationModel/save', payload: { selectUser: undefined, selectRoleList: [] } });
  }

  // 表格数据过滤或跳页
  handleUserTableChange = (pagination, _, sorter) => {
    const { dispatch, AuthorizationModel } = this.props;
    const queryUserParam = { ...AuthorizationModel.queryUserParam, pageNo: pagination.current, pageSize: pagination.pageSize };
    // 排序
    if (sorter.field) {
      const sorterMapper = {};
      queryUserParam.orderField = sorterMapper[sorter.field];
      queryUserParam.sort = SorterOrderMapper[sorter.order];
    } else {
      queryUserParam.orderField = undefined;
      queryUserParam.sort = undefined;
    }
    dispatch({ type: 'AuthorizationModel/findUserByPage', payload: queryUserParam });
  }

  // 用户表格
  getUserTable = () => {
    const height = this.getHeight();
    const { dispatch, findUserByPageLoading, AuthorizationModel: { queryUserParam, userTablePagination, userTableData, selectUser } } = this.props;
    const columns = [
      {
        title: '用户信息', dataIndex: 'username',
        render: (val, record) => {
          const other = [];
          if (record.telephone) {
            other.push(record.telephone);
          } else if (record.email) {
            other.push(record.email);
          }
          const lable = `${val}${other.length > 0 ? `(${other.join(', ')})` : ''}`;
          return (
            <Ellipsis title={record.description ? `${lable}-${record.description}` : val} lines={1}>
              {lable}
            </Ellipsis>
          );
        },
      },
    ];
    return (
      <Fragment>
        <div style={{ marginBottom: 18 }}>
          <Input
            placeholder="登录名、手机号、邮箱(模糊匹配)"
            value={queryUserParam.search}
            onChange={e => dispatch({ type: 'AuthorizationModel/save', payload: { queryUserParam: { ...queryUserParam, search: e.target.value } } })}
            onPressEnter={() => this.findUserByPage({ search: queryUserParam.search })}
          />
        </div>
        <Table
          size="small"
          bordered={false}
          rowKey={record => record.id}
          // rowSelection={{
          //   fixed: false,
          //   // selectedRowKeys: RoleManageModel.selectedRowKeys.map(item => item.id),
          //   onSelect: (changeableRowKeys) => {
          //     console.log(changeableRowKeys);
          //   },
          // }}
          className={styles.selectRowTable}
          rowClassName={record => {
            let className = styles.hoverRow;
            if (selectUser === record.username) {
              className = styles.selectRow;
            }
            return className;
          }}
          onRow={(record) => {
            return {
              onClick: () => {
                if (selectUser !== record.username) {
                  dispatch({ type: 'AuthorizationModel/save', payload: { selectUser: record.username } });
                  dispatch({ type: 'AuthorizationModel/findRoleNameByUser', payload: { username: record.username } });
                }
              },
            }
          }}
          columns={columns}
          loading={findUserByPageLoading}
          pagination={userTablePagination}
          dataSource={userTableData}
          onChange={this.handleUserTableChange}
          scroll={{ x: false, y: height - 135 }}
        />
      </Fragment>
    );
  }

  // 查询数据
  findRoleByPage = (queryParam) => {
    const { dispatch } = this.props;
    dispatch({ type: 'AuthorizationModel/findRoleByPage', payload: { ...queryParam, pageNo: 0 } });
    dispatch({ type: 'AuthorizationModel/save', payload: { selectRole: undefined, selectPermissionList: [] } });
  }

  // 表格数据过滤或跳页
  handleRoleTableChange = (pagination, _, sorter) => {
    const { dispatch, AuthorizationModel } = this.props;
    const queryRoleParam = { ...AuthorizationModel.queryRoleParam, pageNo: pagination.current, pageSize: pagination.pageSize };
    // 排序
    if (sorter.field) {
      const sorterMapper = {};
      queryRoleParam.orderField = sorterMapper[sorter.field];
      queryRoleParam.sort = SorterOrderMapper[sorter.order];
    } else {
      queryRoleParam.orderField = undefined;
      queryRoleParam.sort = undefined;
    }
    dispatch({ type: 'AuthorizationModel/findRoleByPage', payload: queryRoleParam });
  }

  // 角色表格
  getRoleTable = () => {
    const height = this.getHeight();
    const {
      dispatch,
      findRoleByPageLoading,
      findRoleNameByUserLoading,
      singleUserBindRoleLoading,
      singleUserUnBindRoleLoading,
      AuthorizationModel: { selectUser, queryRoleParam, roleTablePagination, roleTableData, selectRoleList, selectRole },
    } = this.props;
    const columns = [
      { title: '角色名称', dataIndex: 'name', render: (val, record) => <Ellipsis title={record.description ? `${val}-${record.description}` : val} lines={1}>{val}</Ellipsis> },
    ];
    return (
      <Fragment>
        <div style={{ marginBottom: 9 }}>
          <Alert
            showIcon
            className={styles.smallAlert}
            type={selectUser ? 'info' : 'warning'}
            message={selectUser ? (
              <Fragment>
                <span>{'为用户分配角色 - { '}</span>
                <Badge offset={[25, 7]} overflowCount={99999999} count={selectRoleList.length}>
                  <span>{selectUser}</span>
                </Badge>
                <span>{' }'}</span>
              </Fragment>
            ) : '请先选择用户再分配角色'}
          />
        </div>
        <div style={{ marginBottom: 9 }}>
          <Input
            placeholder="角色名称(模糊匹配)"
            value={queryRoleParam.name}
            onChange={e => dispatch({ type: 'AuthorizationModel/save', payload: { queryRoleParam: { ...queryRoleParam, name: e.target.value } } })}
            onPressEnter={() => this.findRoleByPage({ name: queryRoleParam.name })}
          />
        </div>
        <Table
          size="small"
          bordered={false}
          rowKey={record => record.name}
          rowSelection={{
            columnWidth: 35,
            columnTitle: '分配',
            // hideDefaultSelections: true,
            fixed: false,
            selectedRowKeys: selectRoleList,
            onChange: (selectedRowKeys) => {
              if (selectUser) {
                dispatch({ type: 'AuthorizationModel/save', payload: { selectRoleList: selectedRowKeys } });
              } else {
                message.info("未选择用户，请先选择用户再分配角色");
              }
            },
            onSelect: (record, selected) => {
              if (!selectUser) return;
              if (selected) {
                // 新增角色
                // console.log("新增角色", selectUser, record.name);
                dispatch({
                  type: 'AuthorizationModel/singleUserBindRole',
                  payload: { username: selectUser, roleName: record.name },
                  successCallBack: result => {
                    message.success(`成功，拥有角色[${result.roleList.length}]个，${result.username} -> ${record.name}`);
                  },
                });
              } else {
                // 删除角色
                // console.log("删除角色", selectUser, record.name);
                dispatch({
                  type: 'AuthorizationModel/singleUserUnBindRole',
                  payload: { username: selectUser, roleName: record.name },
                  successCallBack: result => {
                    message.success(`成功，拥有角色[${result.roleList.length}]个，${result.username} -> ${record.name}`);
                  },
                });
              }
            },
          }}
          className={styles.selectRowTable}
          rowClassName={record => {
            let className = styles.hoverRow;
            if (selectRole === record.name) {
              className = styles.selectRow;
            }
            return className;
          }}
          onRow={(record) => {
            return {
              onClick: e => {
                if (e.target && e.target.className && e.target.className.indexOf("ant-table-selection-column") !== -1) return;
                if (selectRole !== record.name) {
                  dispatch({ type: 'AuthorizationModel/save', payload: { selectRole: record.name } });
                  dispatch({ type: 'AuthorizationModel/findPermissionStrByRole', payload: { roleName: record.name } });
                }
              },
            }
          }}
          columns={columns}
          loading={findRoleByPageLoading || findRoleNameByUserLoading || singleUserBindRoleLoading || singleUserUnBindRoleLoading}
          pagination={roleTablePagination}
          dataSource={roleTableData}
          onChange={this.handleRoleTableChange}
          scroll={{ x: false, y: height - 163 }}
        />
      </Fragment>
    );
  }

  // 权限表单查询
  permissionFormQuery = (e) => {
    if (e) e.preventDefault();
    const { form } = this.props;
    const queryParam = form.getFieldsValue();
    this.findPermissionByPage({ ...queryParam, pageNo: 0 });
    // this.setState({ selectPermissionStrList: [] });
  }

  // 查询数据
  findPermissionByPage = (queryParam) => {
    const { dispatch } = this.props;
    dispatch({ type: 'AuthorizationModel/findPermissionByPage', payload: { ...queryParam, pageNo: 0 } });
    // dispatch({ type: 'AuthorizationModel/save', payload: { selectedRowKeys: [] } });
  }

  // 表格数据过滤或跳页
  handlePermissionTableChange = (pagination, _, sorter) => {
    const { dispatch, AuthorizationModel } = this.props;
    const queryPermissionParam = { ...AuthorizationModel.queryPermissionParam, pageNo: pagination.current, pageSize: pagination.pageSize };
    // 排序
    if (sorter.field) {
      const sorterMapper = {};
      queryPermissionParam.orderField = sorterMapper[sorter.field];
      queryPermissionParam.sort = SorterOrderMapper[sorter.order];
    } else {
      queryPermissionParam.orderField = undefined;
      queryPermissionParam.sort = undefined;
    }
    dispatch({ type: 'AuthorizationModel/findPermissionByPage', payload: queryPermissionParam });
  }

  // 获取url权限信息
  getUrlPermissionInfo = (permission) => {
    const { resourcesUrl, targetClass, targetMethod } = permission;
    let { targetExist, needAuthorization, targetMethodParams, resourcesType } = permission;
    resourcesType = ResourcesTypeMapper[resourcesType];
    if (!resourcesType) resourcesType = ResourcesTypeMapper.error;
    if (!targetClass) return <span>{resourcesType.label}</span>;
    targetExist = TargetExistMapper[targetExist]
    if (!targetExist) targetExist = TargetExistMapper.error;
    needAuthorization = NeedAuthorizationMapper[needAuthorization];
    if (!needAuthorization) needAuthorization = NeedAuthorizationMapper.error;
    if (lodash.trim(targetMethodParams) !== "") {
      const params = lodash.split(targetMethodParams, ',');
      targetMethodParams = [];
      params.forEach(item => {
        let param = item;
        if (param.lastIndexOf('.') !== -1) {
          param = param.substring(param.lastIndexOf('.') + 1);
        }
        targetMethodParams.push(lodash.trim(param));
      });
      targetMethodParams = targetMethodParams.join(', ');
    } else {
      targetMethodParams = '--';
    }
    const packageStr = targetClass.substring(0, targetClass.lastIndexOf('.'));
    const classStr = targetClass.substring(targetClass.lastIndexOf('.') + 1);
    const labelStyle = { display: 'inline-block', width: 100 };
    const valueStyle = {};
    const content = (
      <div>
        <div>
          <span style={labelStyle}>URL地址</span>
          <span style={valueStyle}>{resourcesUrl}</span>
        </div>
        <div>
          <span style={labelStyle}>资源存在</span>
          <span style={{ ...valueStyle, color: targetExist.color }}>{targetExist.label}</span>
        </div>
        <div>
          <span style={labelStyle}>需要权限拦截</span>
          <span style={{ ...valueStyle, color: needAuthorization.color }}>{needAuthorization.label}</span>
        </div>
        <div>
          <span style={labelStyle}>代码 package</span>
          <span style={valueStyle}>{packageStr}</span>
        </div>
        <div>
          <span style={labelStyle}>代码 class</span>
          <span style={valueStyle}>{classStr}</span>
        </div>
        <div>
          <span style={labelStyle}>代码方法名</span>
          <span style={valueStyle}>{targetMethod}</span>
        </div>
        <div>
          <span style={labelStyle}>方法参数</span>
          <span style={valueStyle}>{targetMethodParams}</span>
        </div>
      </div>
    );
    return (
      <Popover placement="rightTop" title={`URL权限详情 - {${permission.title}}`} content={content}>
        <a color={resourcesType.color}>{resourcesType.label}</a>
      </Popover>
    );
  }

  // 权限表格
  getPermissionTable = () => {
    const height = this.getHeight();
    const {
      dispatch,
      form: { getFieldDecorator },
      findPermissionByPageLoading,
      findPermissionStrByRoleLoading,
      singleRoleBindPermissionLoading,
      singleRoleUnBindPermissionLoading,
      AuthorizationModel: { selectRole, queryPermissionParam, permissionTablePagination, permissionTableData, selectPermissionList },
      GlobalEnumModel: { sysNameList },
    } = this.props;
    const columns = [
      { title: '系统名称', dataIndex: 'sysName', width: 200 },
      {
        title: '类型', dataIndex: 'resourcesType', width: 125,
        render: (val, record) => {
          let resourcesType = ResourcesTypeMapper[val];
          if (!resourcesType) resourcesType = ResourcesTypeMapper.error;
          if (lodash.indexOf([1], val) !== -1) {
            return this.getUrlPermissionInfo(record);
          } else {
            return resourcesType.label;
          }
        },
      },
      { title: '标题', dataIndex: 'title', width: 260, render: val => <Ellipsis title={val} lines={1}>{val}</Ellipsis> },
      { title: '标识', dataIndex: 'permissionStr', width: 260, render: (val, record) => <Ellipsis title={`${val}(${record.description})`} lines={1}>{val}</Ellipsis> },
      { title: 'URL资源地址', dataIndex: 'resourcesUrl', width: 260, render: val => <Ellipsis title={val} lines={1}>{val}</Ellipsis> },
    ];
    return (
      <Fragment>
        <div style={{ marginBottom: 9 }}>
          <Alert
            showIcon
            className={styles.smallAlert}
            type={selectRole ? 'info' : 'warning'}
            message={selectRole ? (
              <Fragment>
                <span>{'为角色分配权限 - { '}</span>
                <Badge offset={[28, 7]} overflowCount={99999999} count={selectPermissionList.length}>
                  <span>{selectRole}</span>
                </Badge>
                <span>{' }'}</span>
              </Fragment>
            ) : '请先选择角色再分配权限'}
          />
        </div>
        <Form onSubmit={this.permissionFormQuery} layout="inline" className={styles.queryForm}>
          <Row gutter={{ md: 12, lg: 18, xl: 36 }} style={{ marginBottom: 12 }}>
            <Col span={8}>
              {getFieldDecorator('sysName', { initialValue: queryPermissionParam.sysName })(
                <Select placeholder="所属系统" allowClear={true} size="small">
                  {sysNameList.map(sysName => (<Select.Option key={sysName} value={sysName}>{sysName}</Select.Option>))}
                </Select>
              )}
            </Col>
            <Col span={8}>
              {getFieldDecorator('resourcesType', { initialValue: queryPermissionParam.resourcesType })(
                <Select placeholder="权限类型" allowClear={true} size="small">
                  {ResourcesTypeArray.map(item => (<Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>))}
                </Select>
              )}
            </Col>
            <Col span={8}>
              {getFieldDecorator('needAuthorization', { initialValue: queryPermissionParam.needAuthorization })(
                <Select placeholder="需要授权" allowClear={true} size="small">
                  {NeedAuthorizationArray.map(item => (<Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>))}
                </Select>
              )}
            </Col>
          </Row>
          <Row gutter={{ md: 12, lg: 18, xl: 36 }}>
            <Col span={8}>
              {getFieldDecorator('title', { initialValue: queryPermissionParam.title })(
                <Input placeholder="权限标题(模糊匹配)" size="small" />
              )}
            </Col>
            <Col span={8}>
              {getFieldDecorator('permissionStr', { initialValue: queryPermissionParam.permissionStr })(
                <Input placeholder="权限标识(模糊匹配)" size="small" />
              )}
            </Col>
            <Col span={8}>
              <Button type="primary" htmlType="submit" disabled={findPermissionByPageLoading} size="small">查询</Button>
            </Col>
          </Row>
        </Form>
        <Table
          size="small"
          bordered={false}
          rowKey={record => record.permissionStr}
          rowSelection={{
            columnWidth: 35,
            columnTitle: '分配',
            // hideDefaultSelections: true,
            fixed: false,
            selectedRowKeys: selectPermissionList,
            onChange: (selectedRowKeys) => {
              if (selectRole) {
                dispatch({ type: 'AuthorizationModel/save', payload: { selectPermissionList: selectedRowKeys } });
              } else {
                message.info("未选择角色，请先选择角色再授权");
              }
            },
            onSelect: (record, selected) => {
              if (!selectRole) return;
              if (selected) {
                // 新增权限
                // console.log("新增权限", selectRole, record.permissionStr);
                dispatch({
                  type: 'AuthorizationModel/singleRoleBindPermission',
                  payload: { roleName: selectRole, permissionStr: record.permissionStr },
                  successCallBack: result => {
                    message.success(`成功，拥有权限[${result.permissionList.length}]个，${result.roleName} -> ${record.permissionStr}`);
                  },
                });
              } else {
                // 删除权限
                // console.log("删除权限", selectRole, record.permissionStr);
                dispatch({
                  type: 'AuthorizationModel/singleRoleUnBindPermission',
                  payload: { roleName: selectRole, permissionStr: record.permissionStr },
                  successCallBack: result => {
                    message.success(`成功，拥有权限[${result.permissionList.length}]个，${result.roleName} -> ${record.permissionStr}`);
                  },
                });
              }
            },
          }}
          columns={columns}
          loading={findPermissionByPageLoading || findPermissionStrByRoleLoading || singleRoleBindPermissionLoading || singleRoleUnBindPermissionLoading}
          pagination={permissionTablePagination}
          dataSource={permissionTableData}
          onChange={this.handlePermissionTableChange}
          scroll={{ x: true, y: height - 191 }}
        />
      </Fragment>
    );
  }

  render() {
    const height = this.getHeight();
    const gutter = 36;
    return (
      <PageHeaderLayout>
        <Card bordered={false} bodyStyle={{ padding: `24px ${gutter / 2}px` }}>
          <Row gutter={gutter}>
            <Col span={4} style={{ height }} className={styles.boxBorder}>
              {this.getUserTable()}
            </Col>
            <Col span={5} style={{ height }} className={styles.boxBorder}>
              {this.getRoleTable()}
            </Col>
            <Col span={15} style={{ height }}>
              {this.getPermissionTable()}
            </Col>
          </Row>
        </Card>
      </PageHeaderLayout>
    );
  }
}
